package com.bsoft.server.transport;

import com.alibaba.fastjson.JSON;
import com.bsoft.core.common.RpcRequest;
import com.bsoft.core.common.RpcResponse;
import com.bsoft.core.protocol.MessageHeader;
import com.bsoft.core.protocol.MessageProtocol;
import com.bsoft.core.protocol.MsgStatus;
import com.bsoft.core.protocol.MsgType;
import com.bsoft.server.cache.RpcServiceCache;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.ReflectionUtils;

import java.lang.reflect.Method;

/**
 * 处理客户端发送来的请求
 */
@Slf4j
public class RpcRequestHandler extends SimpleChannelInboundHandler<MessageProtocol<RpcRequest>> {


    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        log.info("client [{}] is connected!", ctx.channel().remoteAddress().toString().substring(1));
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        log.info("client [{}] is disconnected!", ctx.channel().remoteAddress().toString().substring(1));
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, MessageProtocol<RpcRequest> protocol) throws Exception {
        // 拿到客户端发送来的消息，并进行路由到对应的服务
        MessageProtocol<RpcResponse> responseProtocol = new MessageProtocol<>();
        RpcResponse response = new RpcResponse();
        MessageHeader header = protocol.getHeader();
        header.setMsgType(MsgType.RESPONSE.getType());
        header.setStatus(MsgStatus.SUCCESS.getCode());
        // 执行请求
        Object result = null;
        try {
            log.info("request protocol: {}", JSON.toJSONString(protocol));
            result = handler(protocol.getBody());
            // 组装响应
            response.setData(result);
        } catch (Exception e) {
            e.printStackTrace();
            header.setStatus(MsgStatus.SUCCESS.getCode());
            response.setErrMsg(e.getMessage());
        }

        responseProtocol.setHeader(header);
        responseProtocol.setBody(response);
        // 发送结果
        ctx.channel().writeAndFlush(responseProtocol);
    }

    /**
     * 反射找到对应的类，并且执行获取结果
     */
    private Object handler(RpcRequest request) throws Exception{

        // 从缓存中找到目标实现类对象
        Object service = RpcServiceCache.getService(request.getServiceName());
        if (service == null) {
            throw new IllegalStateException("服务不存在");
        }
        // 反射调用接口
        Method method = ReflectionUtils.findMethod(service.getClass(), request.getMethodName(),request.getParameterTypes());
        return ReflectionUtils.invokeMethod(method, service, request.getParameters());
    }

}
